/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Controller;

import Common.Constants;
import Common.Utils;
import Model.AccountModel;
import Model.Dto.jaxb.AccountBalances.AccountBalances;
import Model.Dto.jaxb.AccountBalances.AccountType;
import Model.Dto.jaxb.Accounts.Accounts;
import Model.Dto.jaxb.Transasctions.Transactions;
import Model.TransactionModel;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.sql.Date;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.apache.avalon.framework.logger.ConsoleLogger;
import org.apache.fop.apps.Driver;
import org.xml.sax.InputSource;

/**
 *
 * @author Quang Nhat
 */
public class Accountant extends HttpServlet {

    /**
     * Processes requests for both HTTP
     * <code>GET</code> and
     * <code>POST</code> methods.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/xml;charset=UTF-8");
        try {
            /* TODO output your page here. You may use following sample code. */
            String action = request.getParameter("action");
            if ("listAccount".equalsIgnoreCase(action)) {
                RequestDispatcher rd = request.getRequestDispatcher("/WEB-INF/accountant/accountlist.jsp");
                rd.forward(request, response);
            } else if ("addTransaction".equalsIgnoreCase(action)) {
                RequestDispatcher rd = request.getRequestDispatcher("/WEB-INF/accountant/edittransaction.jsp");
                rd.forward(request, response);
            } else if ("editTransaction".equalsIgnoreCase(action)) {
                String txtId = request.getParameter("Id");
                try {
                    int id = Integer.parseInt(txtId);
                    Transactions res = new Transactions();
                    res.getTransaction().add(TransactionModel.getTransactionById(id));
                    if (res.getTransaction().size() > 0) {
                        request.setAttribute("xmlContent", Utils.MarshallXML(res, false));
                    } else {
                        request.setAttribute("xmlContent", "");
                    }
                } catch (Exception ex) {
                    Utils.ReportException(ex);
                    request.setAttribute(Constants.REQ_MESSAGE, "Invalid Transaction Id.");
                }
                RequestDispatcher rd = request.getRequestDispatcher("/WEB-INF/accountant/edittransaction.jsp");
                rd.forward(request, response);
            } else if ("listTransaction".equalsIgnoreCase(action)) {
                String txtText = request.getParameter("txtText");
                if (txtText != null) {
                    txtText = new String(txtText.getBytes("8859_1"), "UTF8");
                } else {
                    txtText = "";
                }
                String message = "";
                Date minDate = null;
                Date maxDate = null;
                String txtMinDate = request.getParameter("txtMinDate");
                if (txtMinDate != null && txtMinDate.length() > 0) {
                    minDate = Utils.parseDate(txtMinDate);
                    if (minDate == null) {
                        message += "Invalid From Date.";
                    }
                } else {
                    txtMinDate = "";
                }
                String txtMaxDate = request.getParameter("txtMaxDate");
                if (txtMaxDate != null && txtMaxDate.length() > 0) {
                    maxDate = Utils.parseDate(txtMaxDate);
                    if (maxDate == null) {
                        message += "Invalid To Date.";
                    }
                } else {
                    txtMaxDate = "";
                }
                request.setAttribute("txtText", txtText);
                request.setAttribute("txtMaxDate", txtMaxDate);
                request.setAttribute("txtMinDate", txtMinDate);
                try {
                    Transactions res = TransactionModel.searchTransaction(minDate, maxDate, txtText);
                    request.setAttribute("xmlContent", Utils.MarshallXML(res, false));
                    int numItem = res.getTransaction().size();
                    int numPage = numItem / Constants.ITEM_PER_PAGE;
                    if (numItem % Constants.ITEM_PER_PAGE != 0) {
                        numPage++;
                    }
                    request.setAttribute("numPage", numPage);
                    request.setAttribute("pageSize", Constants.ITEM_PER_PAGE);
                } catch (Exception ex) {
                    Utils.ReportException(ex);
                    message += "Invalid Transaction Id.";
                }
                if (message.length() > 0) {
                    request.setAttribute(Constants.REQ_MESSAGE, message);
                } else {
                    request.setAttribute(Constants.REQ_MESSAGE, null);
                }
                RequestDispatcher rd = request.getRequestDispatcher("/WEB-INF/accountant/listtransaction.jsp");
                rd.forward(request, response);
            } else if ("pdfListTransaction".equalsIgnoreCase(action)) {
                OutputStream out = response.getOutputStream();
                String message = "";
                try {
                    response.setContentType("application/pdf");

                    String txtText = request.getParameter("txtText");
                    if (txtText != null) {
                        txtText = new String(txtText.getBytes("8859_1"), "UTF8");
                    } else {
                        txtText = "";
                    }

                    Date minDate = null;
                    Date maxDate = null;
                    String txtMinDate = request.getParameter("txtMinDate");
                    if (txtMinDate != null && txtMinDate.length() > 0) {
                        minDate = Utils.parseDate(txtMinDate);
                        if (minDate == null) {
                            message += "Invalid From Date.";
                        }
                    }
                    String txtMaxDate = request.getParameter("txtMaxDate");
                    if (txtMaxDate != null && txtMaxDate.length() > 0) {
                        maxDate = Utils.parseDate(txtMaxDate);
                        if (maxDate == null) {
                            message += "Invalid To Date.";
                        }
                    }

                    Transactions res = TransactionModel.searchTransaction(minDate, maxDate, txtText);
                    byte[] xmlContent = Utils.Marshall(res, false);

                    String xslFile = getServletContext().getRealPath("/WEB-INF/xml/pdfJournal.xsl");

                    ByteArrayOutputStream foStream = new ByteArrayOutputStream();
                    transformPDF(new ByteArrayInputStream(xmlContent), xslFile, foStream);

                    ByteArrayInputStream fo = new ByteArrayInputStream(foStream.toByteArray());
                    ByteArrayOutputStream pdf = new ByteArrayOutputStream();
                    Driver driver = new Driver(new InputSource(fo), pdf);
                    driver.setLogger(new ConsoleLogger());
                    driver.setRenderer(Driver.RENDER_PDF);
                    driver.run();
                    byte[] content = pdf.toByteArray();
                    out.write(content);
                    out.flush();
                } catch (Exception ex) {
                    Utils.ReportException(ex);
                    message += ex.getMessage();
                }
                if (message.length() > 0) {
                    request.setAttribute(Constants.REQ_MESSAGE, message);
                }
                out.close();
            } else if ("accountBalances".equalsIgnoreCase(action)) {
                String txtDate = request.getParameter("txtDate");
                Date date = null;
                if (txtDate != null) {
                    date = Utils.parseDate(txtDate);
                }
                if (date == null) {
                    java.util.Date currDate = new java.util.Date();
                    date = new Date(currDate.getYear(), currDate.getMonth(), currDate.getDate());
                }
                AccountBalances res = TransactionModel.getJaxbAccountBalances(date);
                request.setAttribute("date", date);
                List<AccountType> accs = res.getAccount();
                Collections.sort(accs, new Comparator<AccountType>() {
                    @Override
                    public int compare(AccountType o1, AccountType o2) {
                        return o1.getAccountNumber().compareTo(o2.getAccountNumber());
                    }
                });
                request.setAttribute("balances", accs);
                RequestDispatcher rd = request.getRequestDispatcher("/WEB-INF/accountant/accountbalances.jsp");
                rd.forward(request, response);
            } else if ("pdfAccountBalances".equalsIgnoreCase(action)) {
                OutputStream out = response.getOutputStream();
                String message = "";


                try {
                    response.setContentType("application/pdf");

                    String txtDate = request.getParameter("txtDate");
                    Date date = null;
                    if (txtDate != null) {
                        date = Utils.parseDate(txtDate);
                    }
                    if (date == null) {
                        java.util.Date currDate = new java.util.Date();
                        date = new Date(currDate.getYear(), currDate.getMonth(), currDate.getDate());
                    }
                    AccountBalances res = TransactionModel.getJaxbAccountBalances(date);
                    
                    byte[] xmlContent = Utils.Marshall(res, false);

                    String xslFile = getServletContext().getRealPath("/WEB-INF/xml/pdfBalances.xsl");

                    ByteArrayOutputStream foStream = new ByteArrayOutputStream();
                    transformPDF(new ByteArrayInputStream(xmlContent), xslFile, foStream);

                    ByteArrayInputStream fo = new ByteArrayInputStream(foStream.toByteArray());
                    ByteArrayOutputStream pdf = new ByteArrayOutputStream();
                    Driver driver = new Driver(new InputSource(fo), pdf);
                    driver.setLogger(new ConsoleLogger());
                    driver.setRenderer(Driver.RENDER_PDF);
                    driver.run();
                    byte[] content = pdf.toByteArray();
                    out.write(content);
                    out.flush();
                } catch (Exception ex) {
                    Utils.ReportException(ex);
                    message += ex.getMessage();
                }
                if (message.length() > 0) {
                    request.setAttribute(Constants.REQ_MESSAGE, message);
                }
                out.close();
            }
        } finally {
        }
    }

    private void transformPDF(InputStream xmlcontent, String xslFile, OutputStream output) {
        try {
            TransformerFactory tf = TransformerFactory.newInstance();
            StreamSource xslSource = new StreamSource(xslFile);
            StreamSource xmlSource = new StreamSource(new InputStreamReader(xmlcontent, "UTF-8"));
            Transformer transformer = tf.newTransformer(xslSource);
            transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");

            StreamResult result = new StreamResult(output);
            transformer.transform(xmlSource, result);

        } catch (Exception ex) {
            Utils.ReportException(ex);
        }
    }
    // <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">

    /**
     * Handles the HTTP
     * <code>GET</code> method.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /**
     * Handles the HTTP
     * <code>POST</code> method.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /**
     * Returns a short description of the servlet.
     *
     * @return a String containing servlet description
     */
    @Override
    public String getServletInfo() {
        return "Short description";
    }// </editor-fold>
}
